package com.hudilao.controller;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.hudilao.common.R;
import com.hudilao.dto.DishDTO;
import com.hudilao.entity.*;
import com.hudilao.service.*;
import com.hudilao.vo.DishVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.web.bind.annotation.*;
import sun.security.krb5.internal.ccache.CredentialsCache;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

//菜品管理
@RestController
@RequestMapping("/dish")
@Slf4j
public class DishController {

    @Autowired
    private DishService dishService;

    @Autowired
    private CategoryService categoryService;

    @Autowired
    private StockService stockService;

    @Autowired
    private SetmealService setmealService;

    @Autowired
    private SetmealDishService setmealDishService;

    @Autowired
    private RedisTemplate redisTemplate;

//    @PostMapping
//    public R<String> save(@RequestBody DishDTO dishDTO){
//
//        //为什么这里两个打印toString只有dishDTO新加的信息-没有dish原有信息呢
//        log.info(dishDTO.toString());
//
//        return R.success(dishDTO.toString());
//    }

    // 管理端：新增菜品
    @PostMapping("/save")
    public R<String> save(@RequestBody Dish dish) {
        log.info("新增菜品: {}", dish);

        // 检查菜品名称是否已存在
        LambdaQueryWrapper<Dish> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Dish::getName, dish.getName());
        Dish existingDish = dishService.getOne(queryWrapper);

        if (existingDish != null) {
            return R.error("菜品名称已存在，请使用其他名称");
        }

        // 保存菜品信息到菜品表
        dishService.saveDish(dish);

        // 尝试直接插入库存记录
        try {

            Stock stock = new Stock();
            stock.setDishId(dish.getId()); // 设置菜品 ID
            stock.setQuantity(0); // 初始化数量为 0
            stock.setDishName(dish.getName());
            //log.info("111");
            stock.setUpdateTime(dish.getCreateTime());

            log.info(stock.getDishId().toString());

            stockService.save(stock); // 保存库存记录

            log.info("库存表新增记录成功，dishId: {}", dish.getId());

        } catch (DuplicateKeyException e) {
            // 唯一约束异常处理，说明库存表中已存在该 dishId 的记录
            log.info("库存表中已存在 dishId={} 的记录，无需新增", dish.getId());
        }

        return R.success("新增菜品成功");
    }




    //管理端：菜品信息分页查询
    @GetMapping("/page")
     public R<Page> page(int page,int pageSize,String name){

         //构造分页构造器
        //page里这个泛型不满足展示信息“菜品类别”，而不是id
        Page<Dish> pageInfo = new Page<>(page,pageSize);

        Page<DishDTO> dishDTOPage = new Page<>();
        log.info("----查询菜品----");
        log.info(name);
        //条件构造器
        LambdaQueryWrapper<Dish> queryWrapper = new LambdaQueryWrapper<>();

        //添加过滤条件
        boolean flag = false;
        if(name != null){
            flag = true;
        }
        else{
            flag = false;
            //return R.error("菜品不存在");
        }
        queryWrapper.like(flag,Dish::getName,name);

        //添加排序条件
        queryWrapper.orderByDesc(Dish::getCreateTime);

        //执行分页查询
        dishService.page(pageInfo,queryWrapper);

        //对象拷贝--除了records
        BeanUtils.copyProperties(pageInfo,dishDTOPage,"records");

        List<Dish> records = pageInfo.getRecords();
        List<DishDTO> list = records.stream().map((item) -> {

            DishDTO dishDto = new DishDTO();
            BeanUtils.copyProperties(item,dishDto);

            //拿到菜品类别id
            Long categoryId = item.getCategoryId();

            //根据id查询分类对象
            Category category = categoryService.getById(categoryId);
            if(category !=null){
                String categoryName = category.getName();
                dishDto.setCategoryName(categoryName);
            }
//            String categoryName = category.getName();
//            dishDto.setCategoryName(categoryName);

            return dishDto;
        }).collect(Collectors.toList());

        dishDTOPage.setRecords(list);

        return R.success(dishDTOPage);
     }


     //管理端：根据id查询菜品信息
     @GetMapping("/edit/{id}")
     public R<Dish> get(@PathVariable Long id){

         return dishService.getDishById(id);
     }


    /**
     * 管理端：修改菜品信息
     * @param dish 包含菜品id和状态信息的请求体
     * @return 修改结果
     */
     @PutMapping("/update")
    public R<String> update(@RequestBody Dish dish){
         log.info(dish.toString());

         dishService.updateDish(dish);

         return R.success("修改菜品成功");
     }

    /**
     * 管理端：根据id删除菜品,如果菜品关联套餐则删除失败
     * @param id 包含菜品id
     * @return 删除结果
     */
    @DeleteMapping("/delete/{id}")
    public R<String> delete(@PathVariable Long id) {
        log.info("删除菜品，菜品ID：{}", id);

        return dishService.deleteDish(id);
    }

    /**
     * 管理端：更新菜品状态（上架/下架），同时禁用包含该菜品的套餐
     * @param dish 包含菜品id和状态信息的请求体
     * @return 更新结果
     */
    @PutMapping("/status")
    public R<String> updateDishStatus(@RequestBody Dish dish) {

        return dishService.updateDishStatus(dish);
    }

    /**
     * 管理端：查询菜品数据
     * @param
     * @return 查询结果，返回菜品数据
     */
    @GetMapping("/list")
    public R<List<Dish>> list_dish(){

        //构建查询条件
        LambdaQueryWrapper<Dish> queryWrapper = new LambdaQueryWrapper<>();
        //queryWrapper.eq(dish.getCategoryId()!=null,Dish::getCategoryId,dish.getCategoryId());

        //停售菜品不显示，不可以加入套餐中
        //查询状态为1的菜品--正在售卖
        queryWrapper.eq(Dish::getStatus,1);

        //添加排序条件
        //先根据sort升序排列，sort相同根据创造时间降序排列
        queryWrapper.orderByAsc(Dish::getSort).orderByDesc(Dish::getCreateTime);

        List<Dish> list = dishService.list(queryWrapper);

        return R.success(list);
    }


    /**
     * 查询所有可售菜品和套餐
     * @return
     */
    @GetMapping({"/user/list"})
    public R<List<DishVO>> list() {

        // Redis key for dishes and setmeals
        String dishesKey = "dishes";
        String setmealsKey = "setmeals";

        // 从 Redis 缓存中查询菜品数据
        ValueOperations<String, List<Dish>> dishValueOps = redisTemplate.opsForValue();
        ValueOperations<String, List<Setmeal>> setmealValueOps = redisTemplate.opsForValue();
        List<Dish> dishes = dishValueOps.get(dishesKey);

        //查询所有可售菜品
        if (CollectionUtils.isEmpty(dishes)) {
            //查询所有可售菜品
            LambdaQueryWrapper<Dish> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(Dish::getStatus, 1);
            queryWrapper.orderByDesc(Dish::getSort);
            dishes = this.dishService.list(queryWrapper);
            //将菜品数据存入 Redis 缓存，设置过期时间为1小时
            dishValueOps.set(dishesKey, dishes, 1, TimeUnit.HOURS);
        }


        // 从 Redis 缓存中查询套餐数据
        List<Setmeal> setmeals = setmealValueOps.get(setmealsKey);
        if (CollectionUtils.isEmpty(setmeals)) {
            //查询所有可售套餐
            LambdaQueryWrapper<Setmeal> setmealLambdaQueryWrapper = new LambdaQueryWrapper<>();
            setmealLambdaQueryWrapper.eq(Setmeal::getStatus, 1);
            setmeals = setmealService.list(setmealLambdaQueryWrapper);
            //将套餐数据存入 Redis 缓存，设置过期时间为1小时
            setmealValueOps.set(setmealsKey, setmeals, 1, TimeUnit.HOURS);
        }

        List<DishVO> dishVOs = dishes.stream().map((dish) -> {
            DishVO dishVO = new DishVO();
            BeanUtils.copyProperties(dish, dishVO);
            dishVO.setType(1);      //设置类型1表示菜品
            dishVO.setStock(stockService.getStockByDishId(dish.getId()));
            return dishVO;
        }).collect(Collectors.toList());

        // 将套餐转换为 DishVO 并添加到列表中
        List<DishVO> setmealVOs = setmeals.stream().map(setmeal -> {
            DishVO dishVO = new DishVO();
            // 将 Setmeal 的属性复制到 DishVO 中
            BeanUtils.copyProperties(setmeal, dishVO);
            dishVO.setType(2); // 设置类型为2表示套餐
            // 获取套餐包含的菜品库存
            LambdaQueryWrapper<SetmealDish> setmealDishQueryWrapper = new LambdaQueryWrapper<>();
            setmealDishQueryWrapper.eq(SetmealDish::getSetmealId, setmeal.getId());
            List<SetmealDish> setmealDishes = setmealDishService.list(setmealDishQueryWrapper);
            Integer minStock = setmealDishes.stream()
                    .map(setmealDish -> stockService.getStockByDishId(setmealDish.getDishId()))
                    .min(Integer::compareTo)
                    .orElse(0); // 如果没有菜品则库存为0

            dishVO.setStock(minStock);
            return dishVO;
        }).collect(Collectors.toList());

        // 按照菜品的分类排序
        dishVOs.sort(Comparator.comparing(DishVO::getCategoryId).thenComparing(DishVO::getSort));

        // 按照套餐的分类排序
        setmealVOs.sort(Comparator.comparing(DishVO::getCategoryId).thenComparing(DishVO::getSort));

        // 合并排序后的菜品和套餐列表
        List<DishVO> combinedList = new ArrayList<>();
        combinedList.addAll(dishVOs);
        combinedList.addAll(setmealVOs);

        if (!combinedList.isEmpty()) {
            return R.success(combinedList);
        } else {
            return R.error("暂无可售菜品");
        }
    }

    /**
     * 根据分类查询菜品
     * @param categoryId
     * @return
     */
    @GetMapping({"/category/{categoryId}"})
    public R<List<Dish>> getByCategoryId(@PathVariable Long categoryId) {

        log.info("根据类别ID查询菜品，类别ID：{}", categoryId);

        //查询处于可售状态的该分类菜品
        LambdaQueryWrapper<Dish> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Dish::getStatus, 1);
        queryWrapper.eq(Dish::getCategoryId, categoryId);
        queryWrapper.orderByDesc(Dish::getSort);

        List<Dish> dishes = this.dishService.list(queryWrapper);

        if (dishes != null && !dishes.isEmpty()) {
            return R.success(dishes);
        } else {
            return R.error("该类别下没有菜品");
        }
    }
}
